//
// Created by 25429 on 2021/2/3.
//


#pragma clang diagnostic push
#pragma ide diagnostic ignored "EndlessLoop"

#include <md_engine.h>

#include <utility>
#include "strategy_engine.h"

static inline int32 mds_api_sample_on_timeout(MdsApiSessionInfoT *pSessionInfo) {
    return 0;
}

static inline int32 mds_api_sample_handle_msg_sh(MdsApiSessionInfoT *pSessionInfo, SMsgHeadT *pMsgHead, void *pMsgBody,
                                                 void *pCallbackParams) {
    if (pMsgHead->msgId == MDS_MSGTYPE_L2_MARKET_DATA_SNAPSHOT) {
        auto *pRspMsg = (MdsMktRspMsgBodyT *) pMsgBody;
        int64_t original_point = system_clock::now().time_since_epoch().count();

        auto it_mkt = ((md_engine *) pCallbackParams)->m_global_l2_mkt.find(pRspMsg->mktDataSnapshot.l2Stock.SecurityID);
        if (it_mkt == ((md_engine *) pCallbackParams)->m_global_l2_mkt.end()) {
            l2_mkt mkt;
            mkt.security = pRspMsg->mktDataSnapshot.l2Stock.SecurityID;
            mkt.deal = pRspMsg->mktDataSnapshot.l2Stock.TradePx;

            ((md_engine *) pCallbackParams)->m_global_l2_mkt[pRspMsg->mktDataSnapshot.l2Stock.SecurityID] = mkt;
        }else{
            it_mkt->second.deal = pRspMsg->mktDataSnapshot.l2Stock.TradePx;
        }
#ifndef DEBUG
        if (((md_engine *) pCallbackParams)->m_config.m_first_buy_target_list2.find(
                pRspMsg->mktDataSnapshot.l2Stock.SecurityID) ==
            ((md_engine *) pCallbackParams)->m_config.m_first_buy_target_list2.end()) {
            // 不在订阅名单
            return 0;
        }
        if (((md_engine *) pCallbackParams)->m_config.m_quote_white_list.find(
                pRspMsg->mktDataSnapshot.l2Stock.SecurityID) ==
            ((md_engine *) pCallbackParams)->m_config.m_quote_white_list.end() &&
            pRspMsg->mktDataSnapshot.l2Stock.TradePx <
            ((md_engine *) pCallbackParams)->m_config.m_all_list[pRspMsg->mktDataSnapshot.l2Stock.SecurityID].up_limit_of_pub_sh) {
            return 0;
        }
#endif
        LOG4CPLUS_TRACE(MY_LOGGER, "md:" << pRspMsg->mktDataSnapshot.l2Stock.SecurityID);
        ((md_engine *) pCallbackParams)->m_strategy_engine->m_quote_queue.enqueue(
                SiriusMDRspMarketMiniField(pRspMsg->mktDataSnapshot.l2Stock.SecurityID,
                                           pRspMsg->mktDataSnapshot.head.updateTime,
                                           pRspMsg->mktDataSnapshot.l2Stock.TradePx,
                                           pRspMsg->mktDataSnapshot.l2Stock.TotalValueTraded * TEN_THOUSANDTH,
                                           pRspMsg->mktDataSnapshot.l2Stock.BidLevels[0].Price,
                                           pRspMsg->mktDataSnapshot.l2Stock.BidLevels[0].OrderQty,
                                           original_point));
    }

    return 0;
}

static inline int32 mds_api_sample_handle_msg(MdsApiSessionInfoT *pSessionInfo, SMsgHeadT *pMsgHead, void *pMsgBody,
                                                 void *pCallbackParams) {
    switch (pMsgHead->msgId) {
        case MDS_MSGTYPE_L2_MARKET_DATA_SNAPSHOT: {
            auto *pRspMsg = (MdsMktRspMsgBodyT *) pMsgBody;
            int64_t original_point = system_clock::now().time_since_epoch().count();

            auto it_mkt = ((md_engine *) pCallbackParams)->m_global_l2_mkt.find(pRspMsg->mktDataSnapshot.l2Stock.SecurityID);
            if (it_mkt == ((md_engine *) pCallbackParams)->m_global_l2_mkt.end()) {
                l2_mkt mkt;
                mkt.security = pRspMsg->mktDataSnapshot.l2Stock.SecurityID;
                mkt.deal = pRspMsg->mktDataSnapshot.l2Stock.TradePx;

                ((md_engine *) pCallbackParams)->m_global_l2_mkt[pRspMsg->mktDataSnapshot.l2Stock.SecurityID] = mkt;
            }else{
                it_mkt->second.deal = pRspMsg->mktDataSnapshot.l2Stock.TradePx;
            }
        }

            return 0;
        case MDS_MSGTYPE_L2_ORDER: {
            /* 处理Level2逐笔委托消息 */
            auto *pRspMsg = (MdsMktRspMsgBodyT *) pMsgBody;
            int64_t original_point = system_clock::now().time_since_epoch().count();
            ((md_engine *) pCallbackParams)->on_l2_order2(&pRspMsg->order, original_point);
        }
            return 0;
        case MDS_MSGTYPE_L2_SSE_ORDER: {
            /* 处理Level2逐笔委托消息 */
            auto *pRspMsg = (MdsMktRspMsgBodyT *) pMsgBody;
            int64_t original_point = system_clock::now().time_since_epoch().count();
            ((md_engine *) pCallbackParams)->on_l2_order2(&pRspMsg->order, original_point);
        }
            return 0;
        default:
            return EFTYPE;
    }
}

static inline int32 mds_api_sample_handle_msg_sz(MdsApiSessionInfoT *pSessionInfo, SMsgHeadT *pMsgHead, void *pMsgBody,
                                                 void *pCallbackParams) {
    switch (pMsgHead->msgId) {
        case MDS_MSGTYPE_L2_TRADE: {
            /* 处理Level2逐笔成交消息 */
            auto *pRspMsg = (MdsMktRspMsgBodyT *) pMsgBody;
            int64_t original_point = system_clock::now().time_since_epoch().count();
            ((md_engine *) pCallbackParams)->on_l2_trade2(&pRspMsg->trade, original_point);
        }

            return 0;
        case MDS_MSGTYPE_L2_ORDER: {
            /* 处理Level2逐笔委托消息 */
            auto *pRspMsg = (MdsMktRspMsgBodyT *) pMsgBody;
            int64_t original_point = system_clock::now().time_since_epoch().count();
            ((md_engine *) pCallbackParams)->on_l2_order2(&pRspMsg->order, original_point);
        }
            return 0;
        default:
            return EFTYPE;
    }
}

static int64 create_order_key(const int32 channel_no, const int32 seq_num) {
    int64 ret = channel_no;
    ret <<= 32;
    ret += seq_num;
    return ret;
}

inline void md_engine::on_l2_trade2(MdsL2TradeT *trade, int64_t original_point) {
    const auto it_mkt = m_global_l2_mkt.find(trade->SecurityID);
    if (it_mkt != m_global_l2_mkt.end()) {
        it_mkt->second.time = trade->TransactTime;
        if (trade->ExecType == '4') // 撤单
        {
            if (trade->OfferApplSeqNum != 0) {
                // 卖单撤单
                const auto it_sell_order = m_global_order_map.find(
                        create_order_key(trade->ChannelNo, trade->OfferApplSeqNum));
                if (it_sell_order != m_global_order_map.end()) {
                    if (it_sell_order->second.OrderType == '2') // 限价
                    {
                        it_mkt->second.sell_levels[it_sell_order->second.Price] -= it_sell_order->second.OrderQty;
                        if (it_mkt->second.sell_levels[it_sell_order->second.Price] <= 0) {
                            it_mkt->second.sell_levels.erase(it_sell_order->second.Price);
                        }
                        publish_l2(it_mkt->second, original_point);
                    }
                    m_global_order_map.erase(it_sell_order);
                } else {
                    LOG4CPLUS_TRACE(MY_LOGGER, "sell order not exist:" << trade->SecurityID);
                }
            } else if (trade->BidApplSeqNum != 0) {
                // 买单撤单
                const auto it_buy_order = m_global_order_map.find(
                        create_order_key(trade->ChannelNo, trade->BidApplSeqNum));
                if (it_buy_order != m_global_order_map.end()) {
                    if (it_buy_order->second.OrderType == '2') // 限价
                    {
                        it_mkt->second.buy_levels[it_buy_order->second.Price] -= it_buy_order->second.OrderQty;
                        if (it_mkt->second.buy_levels[it_buy_order->second.Price] <= 0) {
                            it_mkt->second.buy_levels.erase(it_buy_order->second.Price);
                        }
                        publish_l2(it_mkt->second, original_point);
                    }
                    m_global_order_map.erase(it_buy_order);
                } else {
                    LOG4CPLUS_TRACE(MY_LOGGER, "buy order not exist:" << trade->SecurityID);
                }
            }
        } else if (trade->ExecType == 'F') // 成交
        {
            it_mkt->second.total_deal += trade->TradePrice * trade->TradeQty;
            it_mkt->second.deal = trade->TradePrice;
            // 买单成交
            const auto it_buy_order = m_global_order_map.find(create_order_key(trade->ChannelNo, trade->BidApplSeqNum));
            if (it_buy_order != m_global_order_map.end()) {
                if (it_buy_order->second.OrderType == '2') // 限价
                {
                    it_mkt->second.buy_levels[it_buy_order->second.Price] -= trade->TradeQty;
                    if (it_mkt->second.buy_levels[it_buy_order->second.Price] <= 0) {
                        it_mkt->second.buy_levels.erase(it_buy_order->second.Price);
                    }
                }
                if (it_buy_order->second.OrderQty <= trade->TradeQty) {
                    m_global_order_map.erase(it_buy_order);
                } else {
                    it_buy_order->second.OrderQty -= trade->TradeQty;
                }
            } else {
                LOG4CPLUS_TRACE(MY_LOGGER, "buy order not exist:" << trade->SecurityID);
            }
            //卖单成交
            const auto it_sell_order = m_global_order_map.
                    find(create_order_key(trade->ChannelNo, trade->OfferApplSeqNum));
            if (it_sell_order != m_global_order_map.end()) {
                if (it_sell_order->second.OrderType == '2') // 限价
                {
                    it_mkt->second.sell_levels[it_sell_order->second.Price] -= trade->TradeQty;
                    if (it_mkt->second.sell_levels[it_sell_order->second.Price] <= 0) {
                        it_mkt->second.sell_levels.erase(it_sell_order->second.Price);
                    }
                }
                if (it_sell_order->second.OrderQty <= trade->TradeQty) {
                    m_global_order_map.erase(it_sell_order);
                } else {
                    it_sell_order->second.OrderQty -= trade->TradeQty;
                }
            } else {
                LOG4CPLUS_TRACE(MY_LOGGER, "sell order not exist:" << trade->SecurityID);
            }
            publish_l2(it_mkt->second, original_point);
        }
    } else {
        LOG4CPLUS_TRACE(MY_LOGGER, "mkt not exist:" << trade->SecurityID);
    }
}

inline void md_engine::on_l2_order2(MdsL2OrderT *order, int64_t original_point) {
    m_global_order_map[create_order_key(order->ChannelNo, order->ApplSeqNum)] = *order;

    auto it_mkt = m_global_l2_mkt.find(order->SecurityID);
    if (it_mkt != m_global_l2_mkt.end()) {
        // 预警
        // 大于1000张，大于100块，有成交价，委托价比成交价高0.3
        if (order->Side == '1' &&
            order->OrderQty >= 1000 &&
            order->Price > 100 * 10000 &&
            it_mkt->second.deal != 0 &&
            order->TransactTime < PM_14_57 &&
            order->Price - it_mkt->second.deal > 3000
            ) {
            auto it_alert = m_alert_order.find(order->SecurityID);
            if (it_alert == m_alert_order.end()) {
                m_alert_order[order->SecurityID].emplace_back(*order);
                //it_alert->second.emplace_back(*order);
                LOG4CPLUS_INFO(MY_LOGGER, "emplace_back:" << order->SecurityID << " " << order->Price << " "
                                                              << order->OrderQty);
            } else {
                while (true) {
                    if (it_alert->second.empty()) {
                        break;
                    }
                    if (common_function::pass(it_alert->second.begin()->TransactTime, order->TransactTime) < 60000) {
                        break;
                    }
                    it_alert->second.pop_front();
                    LOG4CPLUS_INFO(MY_LOGGER, "pop_front:" << order->SecurityID);
                }
                it_alert->second.emplace_back(*order);
                if (it_alert->second.size() > 3) {
                    LOG4CPLUS_INFO(MY_LOGGER, "Special quantity:" << order->SecurityID << " " << order->Price << " "
                                                                  << order->OrderQty);
                }
            }
        }
    }
}

inline void md_engine::publish_l2(l2_mkt &mkt, int64_t original_point) {
    LOG4CPLUS_TRACE(MY_LOGGER, "md:" << mkt.security);

    if (mkt.deal == 0) {
        SiriusMDRspMarketMiniField market(mkt.security, mkt.time, mkt.deal, mkt.total_deal * TEN_THOUSANDTH,
                                          original_point);
        for (auto it = mkt.buy_levels.rbegin(); it != mkt.buy_levels.rend();) {
            market.bid1_price = it->first;
            market.bid1_volume = it->second;
            break;
        }

        m_strategy_engine->m_quote_queue.enqueue(market);
    } else {
#ifndef DEBUG
        if (m_config.m_first_buy_target_list2.find(
                mkt.security) ==
            m_config.m_first_buy_target_list2.end()) {
            // 不在订阅名单
            return;
        }
        if (m_config.m_quote_white_list.find(
                mkt.security) ==
            m_config.m_quote_white_list.end() &&
            mkt.deal < m_config.m_all_list[mkt.security].up_limit_of_pub_sz) {
            // 不在白名单，涨幅不超过比例
            return;
        }
#endif
        SiriusMDRspMarketMiniField market(mkt.security, mkt.time, mkt.deal, mkt.total_deal * TEN_THOUSANDTH,
                                          original_point);

        for (auto it = mkt.buy_levels.rbegin(); it != mkt.buy_levels.rend(); ++it) {
            if (it->first > mkt.deal) continue;
            market.bid1_price = it->first;
            market.bid1_volume = it->second;
            break;
        }
        for (auto it = mkt.sell_levels.begin(); it != mkt.sell_levels.end(); ++it) {
            if (it->first < mkt.deal) continue;
            market.offer1_price = it->first;
            market.offer1_volume = it->second;
            break;
        }

        if (market.offer1_price != 0 && market.bid1_price != 0 &&
            market.bid1_price == market.offer1_price) {
            // 只是一笔可以被成交的委托
            return;
        }

        m_strategy_engine->m_quote_queue.enqueue(market);
    }
}

inline void md_engine::go() {
    engine_base::go();
    m_queue.enqueue(SiriusQueueField(SiriusQueueType::QUEUE_MD_INIT));

    new std::thread([&]() {
        SiriusQueueField data[ITEM_SIZE_256];
        while (true) {
            auto size = m_queue.wait_dequeue_bulk(data, ITEM_SIZE_256);
            if (size > 0) {
                for (auto i = 0; i < size; ++i) {
                    switch (data[i].type) {
                        case SiriusQueueType::QUEUE_MD_INIT:
                            m_strategy_engine = new strategy_engine(m_name, this);
                            m_strategy_engine->m_config = m_config;
                            m_strategy_engine->go();
                            break;
                        case SiriusQueueType::QUEUE_TRADE_HOLDING_RSP:
//                            for (const auto &it:data[i].trade_holdings) {
//                                if (m_config.m_all_list.find(it.symbol) == m_config.m_all_list.end()) {
//                                    continue;
//                                }
//                                m_config.m_first_buy_target_list.push_back(it.symbol);
//                                m_config.m_quote_white_list[it.symbol] = 0;
//                            }
                            if (m_config.m_udp_md) {
                                run_ex();
                            } else {
                                run();
                            }

                            break;
                        default:
                            break;
                    }
                }
            }
        }
    });
}

md_engine::md_engine(string name, sirius_engine *sirius) : engine_base(std::move(name)) {
    m_engine_name = "md";
    m_sirius_engine = sirius;
}

static int32
_MdsQuerySample_OnQueryStockStaticInfo(MdsApiSessionInfoT *pSessionInfo,
                                       SMsgHeadT *pMsgHead, void *pMsgBody, MdsQryCursorT *pQryCursor,
                                       void *pCallbackParams) {
    auto *all_static_info = (vector<MdsStockStaticInfoT> *) pCallbackParams;
    auto *pItem = (MdsStockStaticInfoT *) pMsgBody;

    all_static_info->emplace_back(*pItem);

//    printf("... queried StockStaticInfo: {" \
//            "exchId[%" __SPK_FMT_HH__ "u], securityId[%s], securityName[%s], " \
//            "mdProductType[%" __SPK_FMT_HH__ "u], " \
//            "oesSecurityType[%" __SPK_FMT_HH__ "u], " \
//            "subSecurityType[%" __SPK_FMT_HH__ "u], " \
//            "prevClose[%d], upperLimitPrice[%d], lowerLimitPrice[%d]}\n",
//           pItem->exchId,
//           pItem->securityId,
//           pItem->securityName,
//           pItem->mdProductType,
//           pItem->oesSecurityType,
//           pItem->subSecurityType,
//           pItem->prevClose,
//           pItem->upperLimitPrice,
//           pItem->lowerLimitPrice);
    return 0;
}

static int32
_MdsQuerySample_QueryStockStaticInfoList(MdsApiSessionInfoT *pQryChannel,
                                         vector<MdsStockStaticInfoT> *all_static_info,
                                         const MdsQryStockStaticInfoListFilterT *pQryFilter) {
    SLOG_ASSERT(pQryChannel);

    if (__spk_unlikely(!pQryChannel)) {
        SLOG_ERROR("无效的参数! pQryChannel[%p]", pQryChannel);
        return SPK_NEG(EINVAL);
    }

    auto ret = MdsApi_QueryStockStaticInfoList(pQryChannel,
                                               nullptr, (char *) nullptr, pQryFilter,
                                               _MdsQuerySample_OnQueryStockStaticInfo, all_static_info);
    if (__spk_unlikely(ret < 0)) {
        SLOG_ERROR("查询证券静态信息失败 (或回调函数返回负值)! ret[%d]", ret);
        return ret;
    } else if (__spk_unlikely(ret == 0)) {
        SLOG_WARN("未查询到证券静态信息! ret[%d]", ret);
        return 0;
    }

    /* 查询到 ret 条证券静态信息 */
    return ret;
}


void md_engine::run() {
    new std::thread([&]() {
        // 绑定CPU
        common_function::bind_cpu(m_log_title);

        while (true) {
            LOG4CPLUS_INFO(MY_LOGGER, m_log_title << "start mds");
            auto config_file = m_config.m_params[MD_CONFIG_PATH].toString();
            MdsApiClientEnvT client_env = {NULLOBJ_MDSAPI_CLIENT_ENV};
            LOG4CPLUS_INFO(MY_LOGGER, m_log_title << "[MdsApi version]" << MdsApi_GetApiVersion());

            if (!MdsApi_InitAll(&client_env, config_file.toStdString().c_str(),
                                MDSAPI_CFG_DEFAULT_SECTION_LOGGER, MDSAPI_CFG_DEFAULT_SECTION,
                                MDSAPI_CFG_DEFAULT_KEY_TCP_ADDR, MDSAPI_CFG_DEFAULT_KEY_QRY_ADDR,
                                static_cast<char *>(nullptr), static_cast<char *>(nullptr),
                                static_cast<char *>(nullptr),
                                static_cast<char *>(nullptr))) {
                LOG4CPLUS_ERROR(MY_LOGGER, m_log_title << "mds api init all failed");
                sleep(20);
                continue;
            }

            MdsQryStockStaticInfoListFilterT
                    qryFilter = {NULLOBJ_MDS_QRY_STOCK_STATIC_INFO_LIST_FILTER};

            memset(&qryFilter, 0, sizeof(MdsQryStockStaticInfoListFilterT));
            if (m_config.m_exchange == SHANG_HAI) {
                qryFilter.exchId = MDS_EXCH_SSE;
            }
            if (m_config.m_exchange == SHEN_ZHEN) {
                qryFilter.exchId = MDS_EXCH_SZSE;
            }
            qryFilter.oesSecurityType = OES_SECURITY_TYPE_BOND;
            qryFilter.subSecurityType = OES_SUB_SECURITY_TYPE_BOND_CCF;


            vector<MdsStockStaticInfoT> all_static_info;

            auto ret = _MdsQuerySample_QueryStockStaticInfoList(&client_env.qryChannel, &all_static_info, &qryFilter);
            if (__spk_unlikely(ret < 0)) {
                SPK_SLEEP_MS(1000);
                LOG4CPLUS_ERROR(MY_LOGGER, m_log_title << "mds query stock static failed");

                /* 断开并尝试重建连接 */
                MdsApi_DestoryAll(&client_env);
                continue;
            }
            // SPK_SLEEP_MS(1000);

            // 让策略去创建任务
//            m_strategy_engine->create_buy_task(all_static_info);
//            m_strategy_engine->run();

            std::string security_list;
            for (const auto &it: all_static_info) {
                security_list += it.securityId + string(";");
                m_config.m_first_buy_target_list2[it.securityId] = 0;
            }

            const auto timeout_ms = 5000;
            if (m_config.m_exchange == SHANG_HAI) {
                MdsApi_SubscribeByString(&client_env.tcpChannel,
                                         security_list.c_str(), ";",
                                         MDS_EXCH_SSE, MDS_MD_PRODUCT_TYPE_STOCK, MDS_SUB_MODE_SET,
                                         MDS_SUB_DATA_TYPE_L2_SNAPSHOT | MDS_SUB_DATA_TYPE_L2_SSE_ORDER);

                while (true) {
                    /* 等待行情消息到达, 并通过回调函数对消息进行处理 */
                    ret = MdsApi_WaitOnMsg(&client_env.tcpChannel, timeout_ms,
                                           mds_api_sample_handle_msg, (void *) this);
                    if (unlikely(ret < 0)) {
                        if (likely(SPK_IS_NEG_ETIMEDOUT(ret))) {
                            /* 执行超时检查 (检查会话是否已超时) */
                            if (likely(mds_api_sample_on_timeout(&client_env.tcpChannel) == 0)) {
                                continue;
                            }
                            LOG4CPLUS_ERROR(MY_LOGGER, m_log_title << "mds api time out");
                            break;
                        }

                        if (SPK_IS_NEG_EPIPE(ret)) {
                            LOG4CPLUS_ERROR(MY_LOGGER, m_log_title << "mds api disconnected");
                        }
                        break;
                    }
                }
            }
            if (m_config.m_exchange == SHEN_ZHEN) {
                MdsApi_SubscribeByString(&client_env.tcpChannel,
                                         security_list.c_str(), ";",
                                         MDS_EXCH_SZSE, MDS_MD_PRODUCT_TYPE_STOCK, MDS_SUB_MODE_SET,
                                         MDS_SUB_DATA_TYPE_L2_SNAPSHOT | MDS_SUB_DATA_TYPE_L2_ORDER);

                while (true) {
                    /* 等待行情消息到达, 并通过回调函数对消息进行处理 */
                    ret = MdsApi_WaitOnMsg(&client_env.tcpChannel, timeout_ms,
                                           mds_api_sample_handle_msg, (void *) this);
                    if (unlikely(ret < 0)) {
                        if (likely(SPK_IS_NEG_ETIMEDOUT(ret))) {
                            /* 执行超时检查 (检查会话是否已超时) */
                            if (likely(mds_api_sample_on_timeout(&client_env.tcpChannel) == 0)) {
                                continue;
                            }
                            LOG4CPLUS_ERROR(MY_LOGGER, m_log_title << "mds api time out");
                            break;
                        }

                        if (SPK_IS_NEG_EPIPE(ret)) {
                            LOG4CPLUS_ERROR(MY_LOGGER, m_log_title << "mds api disconnected");
                        }
                        break;
                    }
                }
            }
            MdsApi_DestoryAll(&client_env);
        }
    });
}

static int32
_MdsSyncUdpSample_OnTimeout(MdsApiChannelGroupT *pChannelGroup) {
    return 0;
}

void md_engine::run_ex() {
    new std::thread([&]() {
        // 绑定CPU
        common_function::bind_cpu(m_log_title);
        while (true) {
            LOG4CPLUS_INFO(MY_LOGGER, m_log_title << "start mds");
            auto config_file = m_config.m_params[MD_CONFIG_PATH].toString();
            MdsApiClientEnvT cliEnv = {NULLOBJ_MDSAPI_CLIENT_ENV};

            if (!__MdsApi_CheckApiVersion()) {
                SLOG_ERROR("API的头文件版本与库文件版本不匹配, 没有替换头文件或者没有重新编译? " \
                "apiVersion[%s], libVersion[%s]",
                           MDS_APPL_VER_ID, MdsApi_GetApiVersion());
                return (void *) -1;
            } else {
                SLOG_INFO("API version: %s", MdsApi_GetApiVersion());
                LOG4CPLUS_INFO(MY_LOGGER, m_log_title << "[MdsApi version]" << MdsApi_GetApiVersion());
            }

            if (!MdsApi_InitAll(&cliEnv, config_file.toStdString().c_str(),
                                MDSAPI_CFG_DEFAULT_SECTION_LOGGER, MDSAPI_CFG_DEFAULT_SECTION,
                                (char *) NULL, (char *) NULL,
                                "udpServer.Snap1", "",
                                "", "udpServer.Tick2")) {
                LOG4CPLUS_ERROR(MY_LOGGER, m_log_title << "mds api init all failed");
                sleep(20);
                continue;
            }

            std::string security_list;
            for (const auto &it: m_config.m_first_buy_target_list) {
                m_config.m_first_buy_target_list2[it] = 0;
            }

            const auto timeout_ms = 5000;
            if (m_config.m_exchange == SHANG_HAI) {
                while (true) {
                    auto ret = MdsApi_WaitOnUdpChannelGroup(
                            &cliEnv.udpChannelGroup, timeout_ms,
                            mds_api_sample_handle_msg_sh, (void *) this,
                            (MdsApiSessionInfoT **) NULL);
                    if (__spk_unlikely(ret < 0)) {
                        if (__spk_likely(SPK_IS_NEG_ETIMEDOUT(ret))) {
                            ret = _MdsSyncUdpSample_OnTimeout(&cliEnv.udpChannelGroup);
                            if (__spk_likely(ret == 0)) {
                                continue;
                            }
                            SLOG_ERROR("会话已超时, 将断开并重建连接!");
                        } else {
                            SLOG_ERROR("网络操作失败或回调函数返回负值, 将断开并重建连接! " \
                        "ret[%d]", ret);
                        }
                        break;
                    }
                }
            }
            if (m_config.m_exchange == SHEN_ZHEN) {
                while (true) {
                    auto ret = MdsApi_WaitOnUdpChannelGroup(
                            &cliEnv.udpChannelGroup, timeout_ms,
                            mds_api_sample_handle_msg_sz, (void *) this,
                            (MdsApiSessionInfoT **) NULL);
                    if (__spk_unlikely(ret < 0)) {
                        if (__spk_likely(SPK_IS_NEG_ETIMEDOUT(ret))) {
                            ret = _MdsSyncUdpSample_OnTimeout(&cliEnv.udpChannelGroup);
                            if (__spk_likely(ret == 0)) {
                                continue;
                            }
                            SLOG_ERROR("会话已超时, 将断开并重建连接!");
                        } else {
                            SLOG_ERROR("网络操作失败或回调函数返回负值, 将断开并重建连接! " \
                        "ret[%d]", ret);
                        }
                        break;
                    }
                }
            }
            MdsApi_DestoryAll(&cliEnv);
        }
    });
}

#pragma clang diagnostic pop
